package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private RemoteProductService remoteProductService;

    /**
     * @param userId
     * @return 获取大K
     */
    private static String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }

    /**
     * 添加购物车
     * @param skuId  商品skuId
     * @param skuNum  视商品数量
     */

    /**
     * 缓存到redis中  用hash进行缓存
     * 大K 小K v
     * 大K  user:cart:userID
     * 小K  skuId
     * v  cardInfo
     */
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //获取userId 在线程中
        Long userId = SecurityContextHolder.getUserId();
        //构建大K  user:cart:userID
//        String cartKey = "user:cart:" + userId;
        String cartKey = getCartKey(userId);
        //创建hash对象存在redis中
        //小key
        String hashKey = skuId.toString();
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        if (boundHashOperations.hasKey(hashKey)) {// 再次添加
//            String key = "user:lockSku:" + skuId; //分布式锁 保证原子性
//            Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(key, skuId, 5, TimeUnit.MINUTES);
//            if (ifAbsent) {
                synchronized ("hsl") {
                    CartInfo cartInfo = boundHashOperations.get(hashKey);
                    if (cartInfo.getSkuNum() <= 1 && skuNum < 0) {
                        return;
                    }
                    int total = cartInfo.getSkuNum() + skuNum;
                    int threshold = 99;
                    cartInfo.setSkuNum(Math.min(total, threshold));
                    cartInfo.setUpdateTime(new Date());//记录修改时间
                    boundHashOperations.put(hashKey, cartInfo);
//                    redisTemplate.delete(key);
                }
//            } else {
//                return;
//            }

        } else {//首次添加

            Long size = boundHashOperations.size();
            if (++size > 50) {
                throw new ServiceException("商品数量不得大于50");
            }
            CartInfo cardInfo = new CartInfo();

            cardInfo.setCreateTime(new Date());//记录添加时间
            cardInfo.setUpdateTime(new Date());//修改时间

            cardInfo.setUserId(userId);
            cardInfo.setSkuId(skuId);
            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);//内部结构调用
            if (productSkuResult.getCode() == R.FAIL) {//是否降级处理，内部代码错误
                throw new ServiceException(productSkuResult.getMsg());
            }
            ProductSku productSku = productSkuResult.getData();
            cardInfo.setCartPrice(productSku.getSalePrice());//第一次添加购物车的价格
            cardInfo.setSkuPrice(productSku.getSalePrice());//商品的实时价格

            cardInfo.setSkuNum(1);//首次添加 默认数量1
            cardInfo.setThumbImg(productSku.getThumbImg());//缩略图
            cardInfo.setSkuName(productSku.getSkuName());//名称
//        cardInfo.setIsChecked(1);//默认勾选

            boundHashOperations.put(hashKey, cardInfo);//Map集合 put 方法
        }
    }

    /**
     * 查看购物车列表
     *
     * @return
     */
    @Override
    public List<CartInfo> cartList() {

        Long userId = SecurityContextHolder.getUserId();
        //构建大K  user:cart:userID
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();//获取小k对应的value集合

        if (CollectionUtils.isEmpty(cartInfoList)) {
            return new ArrayList<>();
        }
        //1.排序 根据时间倒序
        List<CartInfo> sortedCartInfoList = cartInfoList.stream()
                .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).toList();//降序 与参数顺序相反
        //2.调用远程 批量获取商品的最新价格
        List<Long> skuIdList = sortedCartInfoList.stream().map(CartInfo::getSkuId).toList();
        R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
        if (skuPriceListResult.getCode() == R.FAIL) {
            throw new ServiceException(skuPriceListResult.getMsg());
        }
        List<SkuPrice> skuPriceList = skuPriceListResult.getData();
        Map<Long, BigDecimal> skuIdToSalePriceMap = skuPriceList.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
        for (CartInfo cartInfo : sortedCartInfoList) {
            cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));//实时更新  更新JVM内存中的bean的属性 不是Redis中的cartInfo的数据
        }
        return sortedCartInfoList;
    }

    /**
     * 删除购物车的商品
     *
     * @param skuId
     */
    @Override
    public void deleteCart(Long skuId) {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        //构建大K  user:cart:userID
        String cartKey = getCartKey(userId);
        //获取缓存对象
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        boundHashOperations.delete(skuId.toString());
    }

    /**
     * 更新选中的商品的状态
     *
     * @param skuId
     * @param isChecked
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        //构建大K  user:cart:userID
        String cartKey = getCartKey(userId);
        String hashKey = skuId.toString();
        //获取缓存对象
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        if (boundHashOperations.hasKey(hashKey)) {
            CartInfo cartInfo = boundHashOperations.get(hashKey);
            cartInfo.setIsChecked(isChecked);
            boundHashOperations.put(hashKey, cartInfo);
        }
    }


    /**
     * 更新购物车商品全部选中状态
     *
     * @param isChecked
     */
    @Override
    public void allCheckCart(Integer isChecked) {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        //构建大K  user:cart:userID
        String cartKey = getCartKey(userId);
        //获取缓存对象
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        List<CartInfo> cartInfoList = boundHashOperations.values();
        cartInfoList.forEach(cartInfo -> {
            CartInfo newCartInfo = boundHashOperations.get(cartInfo.getSkuId().toString());
            newCartInfo.setIsChecked(isChecked);
            boundHashOperations.put(cartInfo.getSkuId().toString(), newCartInfo);
        });
    }

    @Override
    public void clearCart() {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        //获取缓存对象
        redisTemplate.delete(cartKey);
    }


    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList = new ArrayList<>();
        String cartKey = getCartKey(userId);
        List<CartInfo> cartCachInfoList = redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(cartCachInfoList))
            for (CartInfo cartInfo : cartCachInfoList) {
                //获取选中商品
                if (cartInfo.getIsChecked().intValue() == 1) {
                    cartInfoList.add(cartInfo);
                }
            }
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        //过滤选中的商品
        List<CartInfo> cartInfoCheckedList = cartCachInfoList.stream().filter((cartInfo) -> cartInfo.getIsChecked() == 1).toList();
        //被选中的商品id
        List<Long> skuIdCheckedList = cartInfoCheckedList.stream().map(CartInfo::getSkuId).toList();
        //获得价格
        R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdCheckedList, SecurityConstants.INNER);
        if (skuPriceListResult.getCode() == R.FAIL) {
            throw new ServiceException(skuPriceListResult.getMsg());
        }
        //数据库价格
        List<SkuPrice> skuPriceCheckedList = skuPriceListResult.getData();
        //list转正Map方便获取数据
        Map<Long, BigDecimal> skuIdToSalePriceMap = skuPriceCheckedList.stream()
                .collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

        for (CartInfo cartInfo : cartInfoCheckedList) {
            cartInfo.setCartPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));//放入购物车时的价格
            cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));//实时价格
            hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
        }
        return true;
         /* @Override
    public Boolean updateCartPrice(Long userId) {

        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
       if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            for (CartInfo cartInfo : cartCachInfoList) {
                if (cartInfo.getIsChecked().intValue() == 1) {
                    SkuPrice skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER).getData();
                    cartInfo.setCartPrice(skuPrice.getSalePrice());
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
                }
            }
        }
        return true;
    }*///垃圾代码 需要优化
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);//小k
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);//value
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            for (CartInfo cartInfo : cartCachInfoList) {
                if (cartInfo.getIsChecked() == 1) {
                    hashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return null;
    }
}